<?php

class fileinfo
{
    private static $mime_types = array(
            'js'   => 'application/x-javascript',
            'css'  => 'text/css',
            'gif'  => 'image/gif',
            'jpg'  => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'jpe'  => 'image/jpeg',
            'png'  => 'image/png',
            'bmp'  => 'image/bmp',
            'ico'  => 'image/x-icon',
            'html' => 'text/html',
            'htm'  => 'text/html',
            'chm'  => 'application/vnd.ms-htmlhelp',
            'swf'  => 'application/x-shockwave-flash',
            'wav'  => 'audio/x-wav',
            'txt'  => 'text/plain',
            'zip'  => 'application/zip',
            'rar'  => 'application/x-rar-compressed',
            'torrent' => 'application/x-bittorrent',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'xslx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'mp3'   => 'audio/mpeg',
            'mmf'   => 'application/x-smaf',
            'amr'   => 'audio/amr',
            'wma'   => 'audio/x-ms-wma',
            'wml'   => 'text/vnd.wap.wml',
            'adp'   => 'audio/adpcm',
            'mfm'   => 'application/vnd.mfmp',
            'aac'   => 'audio/aac',
            'pmd'   => 'application/x-pmd',
            'vmd'   => 'application/vocaltec-media-desc',
            'dxm'   => 'audio/mcdf',
            'seq'   => 'application/vnd.alcatel.SEQ',
            'vox'   => 'application/vnd.alcatel.VOX',
            'mld'   => 'application/x-mld',
            'imy'   => 'audio/imelody',
            'sdt'   => 'application/vnd.siemens-mp.theme', // siemens theme
            'nth'   => 'application/vnd.nok-s40theme',     // S40 theme
            'utz'   => 'application/vnd.uiq.thm',          // uiq theme
            'thm'   => 'application/vnd.eri.thm',          // sonyericsson theme
            'mtf'   => 'application/mtf',                  // motorola theme file
            'mpkg'  => 'application/x-gtar',               // motorola pkg file
            'hme'   => 'application/vnd.smartphone.thm',   // smartphone theme file
            'tsk'   => 'application/vnd.ppc.thm',          // ppc theme file
            'sis'   => 'application/vnd.symbian.install',  // SIS install file
            'sisx'  => 'x-epoc/x-sisx-app',                // SISX install file
            'jad'   => 'text/vnd.sun.j2me.app-descriptor',
            'jar'   => 'application/java-archive',
            'mid'   => 'audio/midi',
            'midi'  => 'audio/midi',
            'pdf'   => 'application/pdf',
            'ipa'   => 'application/x-ipay',               // iPhone/iPod Touch Application
/* 以下未经严格确认 */
            'asf'   => 'video/x-ms-asf',
            'asx'   => 'video/x-ms-asf',
            'avi'   => 'video/x-msvideo',
            'bin'   => 'application/octet-stream',
            'cdf'   => 'application/x-netcdf',
            'csv'   => 'text/comma-separated-values',
            'dll'   => 'application/octet-stream',
            'doc'   => 'application/msword',
            'dot'   => 'application/msword',
            'exe'   => 'application/octet-stream',
            'msi'   => 'application/octet-stream',
            'gz'    => 'application/x-gzip',
            'hqx'   => 'application/mac-binhex40',
            'java'  => 'text/x-java-source',
            'log'   => 'text/plain',
            'mif'   => 'application/vnd.mif',
            'mov'   => 'video/quicktime',
            'movie' => 'video/x-sgi-movie',
            'mpe'   => 'video/mpeg',
            'mpeg'  => 'video/mpeg',
            'mpg'   => 'video/mpeg',
            'mpga'  => 'audio/mpeg',
            'php'   => 'text/plain',
            'ppt'   => 'application/vnd.ms-powerpoint',
            'qt'    => 'video/quicktime',
            'ra'    => 'audio/x-realaudio',
            'ram'   => 'audio/x-pn-realaudio',
            'rm'    => 'audio/x-pn-realaudio',
            'rtf'   => 'text/rtf',
            'shtml' => 'text/html',
            'snd'   => 'audio/basic',
            'sql'   => 'text/plain',
            'tar'   => 'application/x-tar',
            'tgz'   => 'application/x-gtar',
            'tif'   => 'image/tiff',
            'tiff'  => 'image/tiff',
            'wbmp'  => 'image/vnd.wap.wbmp',
            'wm'    => 'video/x-ms-wm',
            'wmv'   => 'video/x-ms-wmv',
            'wmx'   => 'video/x-ms-wmx',
            'wmz'   => 'application/x-ms-wmz',
            'xhtml' => 'application/xhtml+xml',
            'xls'   => 'application/vnd.ms-excel',
            'xlt'   => 'application/vnd.ms-excel',
            'xml'   => 'application/xml',
            'xsl'   => 'text/xml',
            'z'     => 'application/x-compress',
        );

    /**
     * 解析文件的类型。
     *
     * @access public
     * @author pAUL gAO
     * @param string $file_data
     * @param string $filename
     * @return string:''
     */
    public static function parse_file_type($file_data, $filename = '', $tmpfile = '')
    {
        if (isset($file_data{1}) === false)
        {
            return '';
        }

        $extname = '';
        if ($filename)
        {
            $extname = trim(strtolower(substr($filename, strrpos($filename, '.') + 1)));
            if ($extname === 'gz')
            {
                if (stripos($filename, '.tar.gz'))
                {
                    $extname = 'tar.gz';
                }
            }
            elseif ($extname === 'bz2')
            {
                if (stripos($filename, '.tar.bz2'))
                {
                    $extname = 'tar.bz2';
                }
            }
        }

        if ($tmpfile === '' && $filename !== '' && file_exists($filename) === true)
        {
            $tmpfile = $filename;
        }

        $format = '';
        switch (substr($file_data, 0, 2))
        {
            case "\x1F\x8B":
                switch ($extname)
                {
                    case 'mpkg': // for motorola pkg file
                        $format = 'mpkg';
                        break;

                    case 'tar.gz':
                    case 'tgz':
                    case 'mtf': // for motorola theme file
                        $format = 'tar.gz';
                        break;
                }
                break;

             case 'BM':
                if ($extname !== 'txt')
                {
                    $format = 'bmp';
                }
                break;

            case 'MZ':
                if ($extname === 'exe')
                {
                    $format = 'exe';
                }
                break;
        }

        switch (substr($file_data, 0, 3))
        {
            case "\xFF\xD8\xFF":
                $format = 'jpg';
                break;

            case 'MTF':
                $format = 'mtf';
                break;

            case 'CWS':
            case 'FWS':
                if ($extname !== 'txt')
                {
                    $format = 'swf';
                    break;
                }
        }

        switch (substr($file_data, 0, 4))
        {
            case 'MThd':
                if ($extname !== 'txt')
                {
                    $format = 'mid';
                    break;
                }

            case 'RIFF':
                if ($extname == 'wav')
                {
                    $format = 'wav';
                    break;
                }

            case 'cmid':
                $format = 'pmd';
                break;

            case 'MCDF':
                $format = 'dxm';
                break;

            case 'VMHB':
                $format = 'vmd';
                break;

            case '.VOX':
                $format = 'vox';
                break;

            case '.SEQ':
                $format = 'seq';
                break;

            case 'MMMD':
                $format = 'mmf';
                break;

            case 'melo':
                $format = 'mld';
                break;

            case 'Audi':
                $format = 'adp';
                break;

            case 'mfmp':
                $format = 'mfm';
                break;

            case 'GIF8':
                if ($extname !== 'txt')
                {
                    $format = 'gif';
                    break;
                }

            case "\x00\x00\x01\x00":
                if ($extname === 'ico')
                {
                    $format = 'ico';
                    break;
                }

            case "PK\x03\x04":
                switch ($extname)
                {
                    case 'docx':
                    case 'xlsx':
                    case 'pptx':
                    case 'jar':
                    case 'sdt':
                    case 'nth':
                    case 'utz':
                    case 'ipa':
                        $format = $extname;
                        break;

                    default:
                        $format = 'zip';
                        break;
                }
                break;

            case 'Rar!':
                if ($extname !== 'txt')
                {
                    $format = 'rar';
                    break;
                }

            case "\x25PDF":
                $format = 'pdf';
                break;

            case 'ITSF':
                if ($extname !== 'txt')
                {
                    $format = 'chm';
                    break;
                }

            case 'MSCF':
                switch ($extname)
                {
                    case 'tsk':
                    case 'hme':
                        $format = $extname;
                        break;

                    default:
                        $format = 'cab';
                        break;
                }
                break;

            case "\x2ERMF":
                $format = 'rm';
                break;

            case "\x7A\x1A\x20\x10":
                $format = 'sisx';
                break;

            case "\xD0\xCF\x11\xE0":
                if (substr($file_data, 0x200,4) === "\xEC\xA5\xC1\x00" || $extname === 'doc')
                {
                    $format = 'doc';
                }
                elseif (substr($file_data, 0x200, 2) === "\x09\x08" || $extname === 'xls')
                {
                    $format = 'xls';
                }
                elseif ($extname === 'ppt')
                {
                    $format = 'ppt';
                }
                elseif ($extname === 'msi')
                {
                    $format = 'msi';
                }
                break;
        }

        switch (substr($file_data, 0, 5))
        {
            case '#!AMR':
                $format = 'amr';
                break;
        }
        if ($format == '' && $tmpfile)
        {
            if ($extname == 'aac' || $extname == 'wma' || $extname == 'mp3')
            {
                static $getID3 = NULL;

                if ($getID3 === NULL)
                {
                    define('GETID3_INCLUDEPATH', ROOT_PATH . '/framework/library/getid3/');

                    require_once GETID3_INCLUDEPATH . 'getid3.php';

                    // Initialize getID3 engine
                    $getID3 = new getID3;
                }

                // Analyze file and store returned data in $ThisFileInfo
                $FileInfo = $getID3->analyze($tmpfile);

                if (isset($FileInfo['fileformat']))
                {
                    switch ($FileInfo['fileformat'])
                    {
                        case 'aac':
                            $format = 'aac';
                            break;

                        case 'mp3':
                            $format = 'mp3';
                            break;

                        case 'wma':
                            $format = 'wma';
                            break;

                        case 'asf':
                            if (isset($FileInfo['audio']['dataformat']) && $FileInfo['audio']['dataformat'] == 'wma' && isset($FileInfo['video']['dataformat']) == false)
                            {
                                $format = 'wma';
                            }
                            break;

                        default:
                        esq_logs('unknown.fileinfo.log', '1->' . $tmpfile . '@' . var_export($FileInfo, true));
                    }
                }
                else
                {
                    if (substr($file_data, 0, 2) == 'ID')
                    {
                        require_once GETID3_INCLUDEPATH . 'getid3.lib.php';

                        $offset = getid3_lib::BigEndian2Int(substr($file_data, 6, 4), 1) + 0xa;

                        if (substr($file_data, $offset, 4) == 'ADIF')
                        {
                            require_once GETID3_INCLUDEPATH . 'module.audio.aac.php';

                            $fp = fopen($tmpfile, 'rb');
                            $AACinfo['avdataoffset'] = $offset;
                            $AACinfo['avdataend']    = filesize($tmpfile);
                            $class = new getid3_aac($fp, $AACinfo, 'adif');
                            fclose($fp);

                            if (isset($AACinfo['fileformat']))
                            {
                                $format = 'aac';
                            }
                        }
                        else
                        {
                            if (isset($file_data{$offset}) && $file_data{$offset} !== "\xff")
                            {
                                $file_data_length = strlen($file_data);
                                for ($i = $offset; $i < $file_data_length; $i++)
                                {
                                    if ($file_data{$i} == "\xff")
                                    {
                                        $offset = $i;
                                        break;
                                    }
                                }
                            }

                            switch (substr($file_data, $offset, 2))
                            {
                                case "\xff\xf0":
                                case "\xff\xf1":
                                case "\xff\xf9":
                                    require_once GETID3_INCLUDEPATH . 'module.audio.aac.php';

                                    $fp = fopen($tmpfile, 'rb');
                                    $AACinfo['avdataoffset'] = $offset;
                                    $AACinfo['avdataend']    = filesize($tmpfile);
                                    $class = new getid3_aac($fp, $AACinfo, 'adts');
                                    fclose($fp);

                                    if (isset($AACinfo['fileformat']))
                                    {
                                        $format = 'aac';
                                    }

                                    break;

                                default:
                                    require_once GETID3_INCLUDEPATH . 'module.audio.mp3.php';

                                    $fp = fopen($tmpfile, 'rb');
                                    $MP3info['avdataoffset'] = $offset;
                                    $MP3info['avdataend']    = filesize($tmpfile);
                                    $class = new getid3_mp3($fp, $MP3info);
                                    fclose($fp);

                                    if (isset($MP3info['fileformat']))
                                    {
                                        $format = 'mp3';
                                    }
                                    break;
                            }
                        }
                    }
                }
                if ($format == '')
                {
                    esq_logs('unknown.fileinfo.log', '2->' . $tmpfile . '@' . var_export($FileInfo, true));
                }
            }
        }

        if ($format == '')
        {
            if (strtr(substr($file_data, 0x101, 7), array("\x0" => ' ', '0' => ' ')) === 'ustar  ')
            {
                if ($extname == 'thm')
                {
                    $format = 'thm';
                }
                else
                {
                    $format = 'tar';
                }
            }
            elseif (substr($file_data, 8, 4) == "\x19\x04\x00\x10")
            {
                $format = 'sis';
            }
            elseif (substr($file_data, 0, 11) == "d8:announce")
            {
                $format = 'torrent';
            }
            elseif (substr($file_data ,0, 8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
            {
                $format = 'png';
            }
            elseif (stripos($file_data, 'BEGIN:IMELODY') !== false)
            {
                $format = 'imy';
            }
            elseif ($extname == 'log')
            {
                $format = 'log';
            }
            elseif ($extname == 'jad')
            {
                $format = 'jad';
            }
            elseif ($extname == 'sql')
            {
                $format = 'sql';
            }
            elseif ($extname == 'php')
            {
                $format = 'php';
            }
            elseif ($extname == 'txt')
            {
                $format = 'txt';
            }
        }

        return $format;
    }

    /**
     * 更换文件名的扩展名。
     *
     * @access public
     * @param string $filename
     * @param string $extname
     * @return string:''
     */
    public static function replace_filename_extname($filename, $extname)
    {
        if (!$filename || !$extname)
        {
            return '';
        }

        if (strpos($filename, '.') !== false)
        {
            $filename = substr($filename, 0, strrpos($filename, '.'));
        }

        return trim(strtolower($filename . '.' . $extname));
    }

    /**
     * 根据文件名解析文件的MIME。
     *
     * @access public
     * @param string $filename
     * @return string:''
     */
    public static function parse_file_mime($filename)
    {
        if (!$filename)
        {
            return '';
        }

        $extname = trim(strtolower(substr($filename, strrpos($filename, '.') + 1)));
        if (!$extname)
        {
            $extname = $filename;
        }

        return empty(self::$mime_types[$extname]) ? false : self::$mime_types[$extname];
    }

    public static function get_mime_by_extname($extname)
    {
        if (!$extname)
        {
            return '';
        }

        $extname = trim(strtolower($extname));

        return empty(self::$mime_types[$extname]) ? false : self::$mime_types[$extname];
    }

    public static function get_mime_by_filename($filename)
    {
        if (!$filename)
        {
            return '';
        }

        $extname = trim(strtolower(substr($filename, strrpos($filename, '.') + 1)));

        return empty(self::$mime_types[$extname]) ? false : self::$mime_types[$extname];
    }

    /**
     * 解析文件的额外信息，如音频的声道、是否立体声等等。
     *
     * @param string $file_name
     * @param string $extname
     * @return array
     */
    public static function parse_file_extra_info($file_name, $extname)
    {
        $extname = trim(strtolower($extname));

        if (in_array($extname, array('mp3', 'aac', 'wav', 'mid', 'wma')) === false)
        {
            return array();
        }

        static $getID3 = NULL;

        if ($getID3 === NULL)
        {
            define('GETID3_INCLUDEPATH', ROOT_PATH . '/framework/library/getid3/');

            require_once GETID3_INCLUDEPATH . 'getid3.php';

            // Initialize getID3 engine
            $getID3 = new getID3;
        }

        $info = array();

        // Analyze file and store returned data in $ThisFileInfo
        $FileInfo = $getID3->analyze($file_name);

        if (empty($FileInfo['fileformat']) == false)
        {
            if ($extname === 'mp3')
            {
                $info['bitrate']     = $FileInfo['audio']['bitrate']; // 压缩率
                $info['channels']    = $FileInfo['audio']['channels']; // 单声道、立体声
                $info['playtime']    = intval($FileInfo['playtime_seconds']);
            }
            elseif ($extname === 'aac')
            {
                $info['channels']    = $FileInfo['audio']['channels']; // 单声道、立体声
                if (isset($FileInfo['audio']['bitrate']) === true)
                {
                    $info['bitrate']     = $FileInfo['audio']['bitrate']; // 压缩率
                }
                if (isset($FileInfo['playtime_seconds']) === true)
                {
                    $info['playtime']    = intval($FileInfo['playtime_seconds']);
                }
            }
            elseif ($extname === 'wma')
            {
                $info['bitrate']     = $FileInfo['audio']['bitrate']; // 压缩率
                $info['sample_rate'] = $FileInfo['audio']['sample_rate']; // 采样率
                $info['channels']    = $FileInfo['audio']['channels']; // 单声道、立体声
                $info['playtime']    = intval($FileInfo['playtime_seconds']);
            }
            elseif ($extname === 'mid')
            {
                if (isset($FileInfo['playtime_seconds']) == true)
                {
                    $info['tracks']   = $FileInfo['midi']['raw']['tracks']; // 和弦
                    $info['playtime'] = intval($FileInfo['playtime_seconds']);
                }
            }
            elseif ($extname === 'wav')
            {
                $info['playtime']    = intval($FileInfo['playtime_seconds']);
            }
        }

        return $info;
    }

    /**
     * 解析文件的额外信息，如音频的声道、是否立体声等等。
     *
     * @param string $file_name
     * @param string $extname
     * @return array
     */
    public static function parse_file_extra_info_by_file_id($file_id, $extname)
    {
        require_module('framework.filestorage');

        $data = cls_filestorage::find_file_by_fid($file_id);

        return cls_fileinfo::parse_file_extra_info($data['lc_path'], $extname);
    }

    /* PHP 6 内置此函数 */
    public static function gzdecode($data)
    {
        $flags       = ord($data{3});
        $headerlen   = 10;
        $extralen    = 0;
        $filenamelen = 0;

        if ($flags & 4)
        {
            $extralen   = unpack('v' ,substr($data, 10, 2));
            $extralen   = $extralen[1];
            $headerlen += 2 + $extralen;
        }

        /* Filename */
        if ($flags & 8)
        {
            $headerlen = strpos($data, "\x0", $headerlen) + 1;
        }

        /* Comment */
        if ($flags & 16)
        {
            $headerlen = strpos($data, "\x0", $headerlen) + 1;
        }

        /* CRC at end of file */
        if ($flags & 2)
        {
            $headerlen += 2;
        }

        $unpacked = gzinflate(substr($data, $headerlen));
        if ($unpacked === false)
        {
            $unpacked = $data;
        }

        return $unpacked;
     }
}

?>